

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=&#34;light&#34;>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="https://cdn.jsdelivr.net/gh/kzwrime/kzwrime.github.io/img/favicon.png">
  <link rel="icon" type="image/png" href="https://tuchuangrrr.oss-cn-shenzhen.aliyuncs.com/img/kunnan.png">
  <meta name="viewport"
        content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="description" content="">
  <meta name="author" content="霜华">
  <meta name="keywords" content="">
  <title>gdb 调试——栈 - kunzh</title>

  <link  rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.4.1/css/bootstrap.min.css" />


  <link  rel="stylesheet" href="https://cdn.staticfile.org/github-markdown-css/4.0.0/github-markdown.min.css" />
  <link  rel="stylesheet" href="/lib/hint/hint.min.css" />

  
    
    
      
      <link  rel="stylesheet" href="https://cdn.staticfile.org/highlight.js/10.0.0/styles/atelier-lakeside-dark.min.css" />
    
  

  


<!-- 主题依赖的图标库，不要自行修改 -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_pf9vaxs7x7b.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_kmeydafke9r.css">


<link  rel="stylesheet" href="/css/main.css" />

<!-- 自定义样式保持在最底部 -->


  <script  src="/js/utils.js" ></script>
  <script  src="/js/color-schema.js" ></script>
</head>


<body>
  <header style="height: 60vh;">
    <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand"
       href="/">&nbsp;<strong>kunzh</strong>&nbsp;</a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/">
                <i class="iconfont icon-home-fill"></i>
                首页
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/archives/">
                <i class="iconfont icon-archive-fill"></i>
                归档
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/categories/">
                <i class="iconfont icon-category-fill"></i>
                分类
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/tags/">
                <i class="iconfont icon-tags-fill"></i>
                标签
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/about/">
                <i class="iconfont icon-user-fill"></i>
                关于
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/links/">
                <i class="iconfont icon-link-fill"></i>
                友链
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/shuoshuo2/">
                <i class="iconfont icon-speakernotes"></i>
                留言板
              </a>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" data-toggle="modal" data-target="#modalSearch">&nbsp;<i
                class="iconfont icon-search"></i>&nbsp;</a>
          </li>
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" href="javascript:">&nbsp;<i
                class="iconfont icon-dark" id="color-toggle-icon"></i>&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

    <div class="banner intro-2" id="background" parallax=true
         style="background: url('https://rainrime.top/img/SloveniaAlps.jpg') no-repeat center center;
           background-size: cover;">
      <div class="full-bg-img">
        <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
          <div class="container page-header text-center fade-in-up">
            <span class="h2" id="subtitle">
              
            </span>

            
              <div class="mt-3">
  
  
    <span class="post-meta">
      <i class="iconfont icon-date-fill" aria-hidden="true"></i>
      <time datetime="2020-10-17 15:46" pubdate>
        2020年10月17日 下午
      </time>
    </span>
  
</div>

<div class="mt-1">
  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-chart"></i>
      3.4k 字
    </span>
  

  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-clock-fill"></i>
      
      
      49
       分钟
    </span>
  

  
  
    
      <!-- LeanCloud 统计文章PV -->
      <span id="leancloud-post-views-container" class="post-meta" style="display: none">
        <i class="iconfont icon-eye" aria-hidden="true"></i>
        <span id="leancloud-post-views"></span> 次
      </span>
    
  
</div>

            
          </div>

          
        </div>
      </div>
    </div>
  </header>

  <main>
    
      

<div class="container-fluid">
  <div class="row">
    <div class="d-none d-lg-block col-lg-2"></div>
    <div class="col-lg-8 nopadding-md">
      <div class="container nopadding-md" id="board-ctn">
        <div class="py-5" id="board">
          <article class="post-content mx-auto" id="post">
            <!-- SEO header -->
            <h1 style="display: none">gdb 调试——栈</h1>
            
            <div class="markdown-body" id="post-body">
              <p>栈(stack)是程序存放数据的内存区域，是一个 LIFO (后进先出)的数据结构，用于传递函数参数，保存返回地址，保护环境，保存本地信息等。压栈即 PUSH，出栈即 POP，由于栈在内存中由上往下生长，故它们分别对应 rsp - 8 和 rsp + 8。</p>
<p>本文探讨使用 gdb 调试栈相关及运用 vscode 的前端调试的版本，可先往下看，各命令会有说明。</p>
<h3 id="程序源码"><a class="markdownIt-Anchor" href="#程序源码"></a> 程序源码</h3>
<p>以一个计算 0 到 max 整数和的程序为例</p>
<pre><code class="hljs c"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdio.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;ctype.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdlib.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> MAX (1UL &lt;&lt; 20)</span>

<span class="hljs-keyword">typedef</span> <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">long</span> <span class="hljs-keyword">long</span> u64;
<span class="hljs-keyword">typedef</span> <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">int</span> u32;

u32 max_addend = MAX;
<span class="hljs-function">u64 <span class="hljs-title">sum_till_MAX</span><span class="hljs-params">(u32 n)</span></span>
<span class="hljs-function"></span>&#123;
    u64 sum;
    n++;
    sum = n;
    <span class="hljs-keyword">if</span> (n &lt; max_addend)
        sum += sum_till_MAX(n);
    <span class="hljs-keyword">return</span> sum;
&#125;
<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">(<span class="hljs-keyword">int</span> argc, <span class="hljs-keyword">char</span> **argv)</span></span>
<span class="hljs-function"></span>&#123;
    u64 sum = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">if</span> ((argc == <span class="hljs-number">2</span>) &amp;&amp; <span class="hljs-built_in">isdigit</span>(*(argv[<span class="hljs-number">1</span>])))
        max_addend = strtoul(argv[<span class="hljs-number">1</span>], <span class="hljs-literal">NULL</span>, <span class="hljs-number">0</span>);
    <span class="hljs-keyword">if</span> (max_addend &gt; MAX || max_addend == <span class="hljs-number">0</span>)
    &#123;
        <span class="hljs-built_in">fprintf</span>(<span class="hljs-built_in">stderr</span>, <span class="hljs-string">&quot;Invalid number is specified\n&quot;</span>);
        <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>;
    &#125;
    sum = sum_till_MAX(<span class="hljs-number">0</span>);
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">&quot;sum(0..%u) = %llu\n&quot;</span>, max_addend, sum);
    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
&#125;</code></pre>
<p>注：以下运行时全部预设运行参数为 10，相当于 <code>./sum 10</code></p>
<ul>
<li>
<p>直接使用命令行 gdb 请输入 <code>set args 10</code>，使用<code>show args</code>查看设置好的运行参数</p>
<pre><code class="hljs sql">(gdb) <span class="hljs-keyword">set</span> args <span class="hljs-number">10</span>
(gdb) <span class="hljs-keyword">show</span> args
Argument <span class="hljs-keyword">list</span> <span class="hljs-keyword">to</span> give program being debugged <span class="hljs-keyword">when</span> it <span class="hljs-keyword">is</span>   started <span class="hljs-keyword">is</span> <span class="hljs-string">&quot;10&quot;</span>.</code></pre>
</li>
<li>
<p>使用配合 gdb 的 vscode 前端调试器请在 <code>.vscode/launch.json</code> 添加一项 <code>&quot;args&quot;: [&quot;10&quot;],</code>，如:</p>
</li>
</ul>
<h3 id="gdb-命令行调试简要说明"><a class="markdownIt-Anchor" href="#gdb-命令行调试简要说明"></a> GDB 命令行调试简要说明</h3>
<p>先用 gcc 编译：<code>gcc sum.c -o sum -g</code>，然后输入<code>gdb sum</code>即可进入 gdb 愉快调试。此处附一份简单的命令表格</p>
<table>
<thead>
<tr>
<th>命令</th>
<th>含义描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>file</td>
<td>装入想要的调试的可执行文件。</td>
</tr>
<tr>
<td>run</td>
<td>执行当前被调试的程序。</td>
</tr>
<tr>
<td>kill</td>
<td>终止正在调试的程序。</td>
</tr>
<tr>
<td>step</td>
<td>执行一行源代码而且进入函数内部。</td>
</tr>
<tr>
<td>next</td>
<td>执行一行源代码但不进入函数内部。</td>
</tr>
<tr>
<td>break</td>
<td>在代码里设置断点，这将使程序执行到这里时被挂起。</td>
</tr>
<tr>
<td>print</td>
<td>打印表达式或变量的值，或打印内存中某个变量开始的一段连续区域的值，还以用来对变量进行赋值。</td>
</tr>
<tr>
<td>display</td>
<td>设置自动显示的表达式或变量，当程序停住或在单步追踪时，这些变量会自动显示其当前值。</td>
</tr>
<tr>
<td>list</td>
<td>列出产生执行文件的源代码的一部分。</td>
</tr>
<tr>
<td>quit</td>
<td>退出 GDB。</td>
</tr>
<tr>
<td>watch</td>
<td>使你能监视一个变量的值而不管它何时被改变。</td>
</tr>
<tr>
<td>backtrace（或 bt）</td>
<td>回溯追踪，显示栈帧。</td>
</tr>
<tr>
<td>frame n</td>
<td>定位到发生错误的代码段，<code>n</code> 为 <code>backtrace</code> 命令的输出结果中的行号。</td>
</tr>
<tr>
<td>examine</td>
<td>查看内存地址中的值。</td>
</tr>
<tr>
<td>jump</td>
<td>是程序跳转执行。</td>
</tr>
<tr>
<td>signal</td>
<td>产生信号量。</td>
</tr>
<tr>
<td>return</td>
<td>强制函数返回。</td>
</tr>
<tr>
<td>call</td>
<td>强制调用函数。</td>
</tr>
<tr>
<td>make</td>
<td>使用户不退出 GDB 就可以重新产生可执行文件。</td>
</tr>
<tr>
<td>shell</td>
<td>使用户不离开 GDB 就执行 Linux 的 shell 命令。</td>
</tr>
<tr>
<td>info</td>
<td>显示信息</td>
</tr>
</tbody>
</table>
<ul>
<li><code>break</code> + 函数名 / 行号 / 文件名:行号 / 文件名:函数名 / +偏移量 / -偏移量 / *地址</li>
<li><code>info</code> + b / r /…</li>
<li><code>bt N</code> 显示所有栈帧，<code>bt N</code> 显示开头<code>N</code>个栈帧，<code>bt -N</code> 显示最后<code>N</code>个栈帧，<code>bt full -N</code> 再加上显示局部变量。</li>
</ul>
<p>在寄存器名前加 <code>$</code> ，即可显示各个寄存器的内容，如<code>p $eax</code>。可以使用<code>p/格式 变量</code>来格式化输出。</p>
<table>
<thead>
<tr>
<th>格式</th>
<th>说明，显示为：</th>
</tr>
</thead>
<tbody>
<tr>
<td>x</td>
<td>十六进制数</td>
</tr>
<tr>
<td>d</td>
<td>十进制数</td>
</tr>
<tr>
<td>u</td>
<td>无符号十进制数</td>
</tr>
<tr>
<td>o</td>
<td>八进制数</td>
</tr>
<tr>
<td>t</td>
<td>二进制数</td>
</tr>
<tr>
<td>a</td>
<td>地址</td>
</tr>
<tr>
<td>c</td>
<td>字符(ASCII)</td>
</tr>
<tr>
<td>f</td>
<td>浮点数</td>
</tr>
<tr>
<td>s</td>
<td>字符串</td>
</tr>
<tr>
<td>i</td>
<td>机器语言(仅在 x 命令中可用)</td>
</tr>
</tbody>
</table>
<p>使用 x 命令可以显示内存的内容，其来由是<code>eXamining</code>，格式为 <code>x/格式 地址</code>，如<code>x/i $pc</code>为显示指令指针指向的命令。格式可具化为<code>x/NFU ADDR</code>，N 为重复次数，F 为上述格式，U 为下表所示。</p>
<table>
<thead>
<tr>
<th>单位</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>b</td>
<td>字节</td>
</tr>
<tr>
<td>h</td>
<td>半字（2字节）</td>
</tr>
<tr>
<td>w</td>
<td>字（4字节）（默认）</td>
</tr>
<tr>
<td>g</td>
<td>双字（8字节）</td>
</tr>
</tbody>
</table>
<h3 id="vscode-调试简要说明"><a class="markdownIt-Anchor" href="#vscode-调试简要说明"></a> vscode 调试简要说明</h3>
<p>介绍一下 vscode 的调试。<code>ctrl shift o</code>可以打开调试界面及左边第四个图标，配置好 <code>launch.json</code> 后，在对应源文件按下 F5 即可进行调试，行号左边可以打上断点，右键可以选择条件断点或记录点。左边为调试信息。可结合下图查看。</p>
<ul>
<li><code>Locals</code> 为当前函数局部变量，相当于 gdb 中<code>info args</code>加上<code>info locals</code>；</li>
<li><code>监视</code>中可以输入表达式监控全局变量等，相当于 gdb 命令<code>watch</code>;</li>
<li><code>调用堆栈</code>即展示堆栈信息，相当于<code>bt</code>(backtrace)，点击可切换栈帧，查看不同函数层的局部变量。</li>
<li>vscode 在调试控制台输入命令时，需要在正常的 gdb 命令前加上 -exec.</li>
</ul>
<p><img src="https://tuchuangrrr.oss-cn-shenzhen.aliyuncs.com/img/vscode-show01.png" srcset="/img/loading.gif" alt="image-20201017132425496" /></p>
<h3 id="略读反汇编"><a class="markdownIt-Anchor" href="#略读反汇编"></a> 略读反汇编</h3>
<p>展示<code>main</code>的部分反汇编并做了点注释。再次提醒，vscode 请在调试控制台输入如 <code>-exec disas main</code>等<code>-exec</code>开头的指令。</p>
<pre><code class="hljs pf">(gdb) disas main
Dump of assembler code <span class="hljs-keyword">for</span> function main:
   <span class="hljs-number">0</span>x00000000080007af <span class="hljs-variable">&lt;+0&gt;</span>:     push   %rbp                       <span class="hljs-comment"># 1. 保存上层帧的栈指针</span>
   <span class="hljs-number">0</span>x00000000080007b0 <span class="hljs-variable">&lt;+1&gt;</span>:     mov    %rsp,%rbp                  <span class="hljs-comment"># 2. 将新的栈帧赋给栈指针</span>
   <span class="hljs-number">0</span>x00000000080007b3 <span class="hljs-variable">&lt;+4&gt;</span>:     sub    <span class="hljs-variable">$0x20</span>,%rsp                 <span class="hljs-comment"># 手动管理栈对应的内存，打算用个20字节</span>
   <span class="hljs-number">0</span>x00000000080007b7 <span class="hljs-variable">&lt;+8&gt;</span>:     mov    %edi,-<span class="hljs-number">0</span>x14(%rbp)           <span class="hljs-comment"># 把 argc 丢进去             4字</span>
   <span class="hljs-number">0</span>x00000000080007ba <span class="hljs-variable">&lt;+11&gt;</span>:    mov    %rsi,-<span class="hljs-number">0</span>x20(%rbp)           <span class="hljs-comment"># 再把 **argv 丢进去         8字</span>
   <span class="hljs-number">0</span>x00000000080007be <span class="hljs-variable">&lt;+15&gt;</span>:    movq   <span class="hljs-variable">$0x0</span>,-<span class="hljs-number">0</span>x8(%rbp)            <span class="hljs-comment"># 再把 usum = 0 放进去       8字</span>
......
   <span class="hljs-number">0</span>x000000000800085c <span class="hljs-variable">&lt;+173&gt;</span>:   mov    <span class="hljs-variable">$0x0</span>,%edi                  <span class="hljs-comment"># 传参，相当于预备 sum_till_MAX(0)</span>
   <span class="hljs-number">0</span>x0000000008000861 <span class="hljs-variable">&lt;+178&gt;</span>:   callq  <span class="hljs-number">0</span>x800077a <span class="hljs-variable">&lt;sum_till_MAX&gt;</span>   <span class="hljs-comment"># 调用，call 自动把函数返回值入栈(0x8000866)</span>
   <span class="hljs-number">0</span>x0000000008000866 <span class="hljs-variable">&lt;+183&gt;</span>:   mov    %rax,-<span class="hljs-number">0</span>x8(%rbp)
   <span class="hljs-number">0</span>x000000000800086a <span class="hljs-variable">&lt;+187&gt;</span>:   mov    <span class="hljs-number">0</span>x2007a0(%rip),%eax        <span class="hljs-comment"># 0x8201010 &lt;max_addend&gt;</span>
   <span class="hljs-number">0</span>x0000000008000870 <span class="hljs-variable">&lt;+193&gt;</span>:   mov    -<span class="hljs-number">0</span>x8(%rbp),%rdx
   <span class="hljs-number">0</span>x0000000008000874 <span class="hljs-variable">&lt;+197&gt;</span>:   mov    %eax,%esi
   <span class="hljs-number">0</span>x0000000008000876 <span class="hljs-variable">&lt;+199&gt;</span>:   lea    <span class="hljs-number">0</span>xb4(%rip),%rdi            <span class="hljs-comment"># 0x8000931</span>
   <span class="hljs-number">0</span>x000000000800087d <span class="hljs-variable">&lt;+206&gt;</span>:   mov    <span class="hljs-variable">$0x0</span>,%eax
   <span class="hljs-number">0</span>x0000000008000882 <span class="hljs-variable">&lt;+211&gt;</span>:   callq  <span class="hljs-number">0</span>x8000620 <span class="hljs-variable">&lt;printf@plt&gt;</span>
   <span class="hljs-number">0</span>x0000000008000887 <span class="hljs-variable">&lt;+216&gt;</span>:   mov    <span class="hljs-variable">$0x0</span>,%eax
   <span class="hljs-number">0</span>x000000000800088c <span class="hljs-variable">&lt;+221&gt;</span>:   leaveq                           <span class="hljs-comment"># 删除栈帧，执行和1.2.完全相反的指令</span>
   <span class="hljs-number">0</span>x000000000800088d <span class="hljs-variable">&lt;+222&gt;</span>:   retq                             <span class="hljs-comment"># 子程序返回指令，将返回地址 POP 到 $rip (PC)</span>
End of assembler dump.</code></pre>
<p>然后看看<code>sum_till_MAX()</code></p>
<pre><code class="hljs llvm">(gdb) disas sum_till_MAX(unsigned int) 
Dump of assembler code for function sum_till_MAX(unsigned int):
   <span class="hljs-number">0x000000000000071a</span> &lt;+<span class="hljs-number">0</span>&gt;:     push   <span class="hljs-symbol">%rbp</span>                       # <span class="hljs-number">1</span>. 保存上层帧的栈指针
   <span class="hljs-number">0x000000000000071b</span> &lt;+<span class="hljs-number">1</span>&gt;:     mov    <span class="hljs-symbol">%rsp</span>,<span class="hljs-symbol">%rbp</span>                  # <span class="hljs-number">2</span>. 将新的栈帧赋给栈指针
   <span class="hljs-number">0x000000000000071e</span> &lt;+<span class="hljs-number">4</span>&gt;:     <span class="hljs-keyword">sub</span>    $<span class="hljs-number">0x20</span>,<span class="hljs-symbol">%rsp</span>                 # 手动管理栈对应的内存，打算用个<span class="hljs-number">20</span>字节
   <span class="hljs-number">0x0000000000000722</span> &lt;+<span class="hljs-number">8</span>&gt;:     mov    <span class="hljs-symbol">%edi</span>,<span class="hljs-number">-0</span><span class="hljs-keyword">x</span><span class="hljs-number">14</span>(<span class="hljs-symbol">%rbp</span>)           # u 丢进去
   <span class="hljs-number">0x0000000000000725</span> &lt;+<span class="hljs-number">11</span>&gt;:    addl   $<span class="hljs-number">0x1</span>,<span class="hljs-number">-0</span><span class="hljs-keyword">x</span><span class="hljs-number">14</span>(<span class="hljs-symbol">%rbp</span>)           # u++
   <span class="hljs-number">0x0000000000000729</span> &lt;+<span class="hljs-number">15</span>&gt;:    mov    <span class="hljs-number">-0</span><span class="hljs-keyword">x</span><span class="hljs-number">14</span>(<span class="hljs-symbol">%rbp</span>),<span class="hljs-symbol">%eax</span>           
   <span class="hljs-number">0x000000000000072c</span> &lt;+<span class="hljs-number">18</span>&gt;:    mov    <span class="hljs-symbol">%rax</span>,<span class="hljs-number">-0</span><span class="hljs-keyword">x</span><span class="hljs-number">8</span>(<span class="hljs-symbol">%rbp</span>)            # sum = n
   <span class="hljs-number">0x0000000000000730</span> &lt;+<span class="hljs-number">22</span>&gt;:    mov    <span class="hljs-number">0x2008da</span>(<span class="hljs-symbol">%rip</span>),<span class="hljs-symbol">%eax</span>        # <span class="hljs-number">0x201010</span> &lt;max_addend&gt;
   <span class="hljs-number">0x0000000000000736</span> &lt;+<span class="hljs-number">28</span>&gt;:    cmp    <span class="hljs-symbol">%eax</span>,<span class="hljs-number">-0</span><span class="hljs-keyword">x</span><span class="hljs-number">14</span>(<span class="hljs-symbol">%rbp</span>)           # if (n &lt; max_addend)
   <span class="hljs-number">0x0000000000000739</span> &lt;+<span class="hljs-number">31</span>&gt;:    jae    <span class="hljs-number">0x749</span> &lt;sum_till_MAX(unsigned int)+<span class="hljs-number">47</span>&gt;
   <span class="hljs-number">0x000000000000073b</span> &lt;+<span class="hljs-number">33</span>&gt;:    mov    <span class="hljs-number">-0</span><span class="hljs-keyword">x</span><span class="hljs-number">14</span>(<span class="hljs-symbol">%rbp</span>),<span class="hljs-symbol">%eax</span>
   <span class="hljs-number">0x000000000000073e</span> &lt;+<span class="hljs-number">36</span>&gt;:    mov    <span class="hljs-symbol">%eax</span>,<span class="hljs-symbol">%edi</span>
   <span class="hljs-number">0x0000000000000740</span> &lt;+<span class="hljs-number">38</span>&gt;:    callq  <span class="hljs-number">0x71a</span> &lt;sum_till_MAX(unsigned int)&gt;
   <span class="hljs-number">0x0000000000000745</span> &lt;+<span class="hljs-number">43</span>&gt;:    <span class="hljs-keyword">add</span>    <span class="hljs-symbol">%rax</span>,<span class="hljs-number">-0</span><span class="hljs-keyword">x</span><span class="hljs-number">8</span>(<span class="hljs-symbol">%rbp</span>)
   <span class="hljs-number">0x0000000000000749</span> &lt;+<span class="hljs-number">47</span>&gt;:    mov    <span class="hljs-number">-0</span><span class="hljs-keyword">x</span><span class="hljs-number">8</span>(<span class="hljs-symbol">%rbp</span>),<span class="hljs-symbol">%rax</span>
   <span class="hljs-number">0x000000000000074d</span> &lt;+<span class="hljs-number">51</span>&gt;:    leaveq                            # 删除栈帧，执行和<span class="hljs-number">1.2</span>.完全相反的指令
   <span class="hljs-number">0x000000000000074e</span> &lt;+<span class="hljs-number">52</span>&gt;:    retq                              # 子程序返回指令，将返回地址 POP 到 $rip (PC)
End of assembler dump.</code></pre>
<h3 id="运行并解读一个程序的栈信息"><a class="markdownIt-Anchor" href="#运行并解读一个程序的栈信息"></a> 运行并解读一个程序的栈信息</h3>
<p>以下</p>
<ul>
<li>条件断点，在 n==2 时中断函数(第15行)，此时是第二次调用</li>
<li><code>info breakpoints</code>显示断点信息</li>
<li><code>run</code>开始运行直到断点</li>
<li><code>backtrace</code>查看栈信息，此时可以看见三个栈帧，当前的<code>#0</code>在最上面（内存位置最低）</li>
<li>查看寄存器中的程序计数器(<code>%rip instruction pointer</code>)和栈基指针(<code>%rbp base pointer</code>)</li>
<li>从栈顶指针(<code>%rsp stack pointer</code>)开始以十六进制(x)显示 40 个 8 字</li>
<li><code>frame</code>查看当前帧，<code>frame</code>查看上一个帧<code>#1</code></li>
</ul>
<pre><code class="hljs angelscript">(gdb) b <span class="hljs-number">15</span> <span class="hljs-keyword">if</span> n==<span class="hljs-number">2</span>
Note: breakpoint <span class="hljs-number">1</span> also <span class="hljs-keyword">set</span> at pc <span class="hljs-number">0x8000730</span>.
Breakpoint <span class="hljs-number">2</span> at <span class="hljs-number">0x8000730</span>: file /mnt/c/Users/kunzh/C&amp;C++/test/gdb-stack/sum.c, line <span class="hljs-number">15.</span>
(gdb) info b
Num     Type           Disp Enb Address            What
<span class="hljs-number">1</span>       breakpoint     keep y   <span class="hljs-number">0x0000000008000730</span> <span class="hljs-keyword">in</span> sum_till_MAX(unsigned <span class="hljs-built_in">int</span>)
                                                   at /mnt/c/Users/kunzh/C&amp;C++/test/gdb-stack/sum.c:<span class="hljs-number">15</span>
        stop only <span class="hljs-keyword">if</span> n==<span class="hljs-number">2</span>
        breakpoint already hit <span class="hljs-number">1</span> time
<span class="hljs-number">2</span>       breakpoint     keep y   <span class="hljs-number">0x0000000008000730</span> <span class="hljs-keyword">in</span> sum_till_MAX(unsigned <span class="hljs-built_in">int</span>)
                                                   at /mnt/c/Users/kunzh/C&amp;C++/test/gdb-stack/sum.c:<span class="hljs-number">15</span>
        stop only <span class="hljs-keyword">if</span> n==<span class="hljs-number">2</span>
(gdb) r
Starting program: /mnt/c/Users/kunzh/C&amp;C++/test/gdb-stack/sum 

Breakpoint <span class="hljs-number">1</span>, sum_till_MAX (n=<span class="hljs-number">2</span>) at /mnt/c/Users/kunzh/C&amp;C++/test/gdb-stack/sum.c:<span class="hljs-number">15</span>
<span class="hljs-number">15</span>          <span class="hljs-keyword">if</span> (n &lt; max_addend)
(gdb) bt
#<span class="hljs-number">0</span>  sum_till_MAX (n=<span class="hljs-number">2</span>) at /mnt/c/Users/kunzh/C&amp;C++/test/gdb-stack/sum.c:<span class="hljs-number">15</span>
#<span class="hljs-number">1</span>  <span class="hljs-number">0x0000000008000745</span> <span class="hljs-keyword">in</span> sum_till_MAX (n=<span class="hljs-number">1</span>)
    at /mnt/c/Users/kunzh/C&amp;C++/test/gdb-stack/sum.c:<span class="hljs-number">16</span>
#<span class="hljs-number">2</span>  <span class="hljs-number">0x0000000008000800</span> <span class="hljs-keyword">in</span> main (argc=<span class="hljs-number">1</span>, argv=<span class="hljs-number">0x7ffffffee288</span>)
    at /mnt/c/Users/kunzh/C&amp;C++/test/gdb-stack/sum.c:<span class="hljs-number">29</span>
(gdb) i r rip rbp rsp
rip            <span class="hljs-number">0x8000730</span>        <span class="hljs-number">0x8000730</span> &lt;sum_till_MAX(unsigned <span class="hljs-built_in">int</span>)+<span class="hljs-number">22</span>&gt;
rbp            <span class="hljs-number">0x7ffffffee140</span>   <span class="hljs-number">0x7ffffffee140</span>
rsp            <span class="hljs-number">0x7ffffffee120</span>   <span class="hljs-number">0x7ffffffee120</span>
(gdb) x/<span class="hljs-number">40</span>x $sp
<span class="hljs-number">0x7ffffffee120</span>: <span class="hljs-number">0x00000000</span>      <span class="hljs-number">0x00000000</span>      <span class="hljs-number">0x00000000</span>      <span class="hljs-number">0x00000002</span>
<span class="hljs-number">0x7ffffffee130</span>: <span class="hljs-number">0x00000000</span>      <span class="hljs-number">0x00000000</span>      <span class="hljs-number">0x00000002</span>      <span class="hljs-number">0x00000000</span>
<span class="hljs-number">0x7ffffffee140</span>: <span class="hljs-number">0xfffee170</span>      <span class="hljs-number">0x00007fff</span>      <span class="hljs-number">0x08000745</span>      <span class="hljs-number">0x00000000</span>
<span class="hljs-number">0x7ffffffee150</span>: <span class="hljs-number">0xfffee1b8</span>      <span class="hljs-number">0x00007fff</span>      <span class="hljs-number">0x00f0b5ff</span>      <span class="hljs-number">0x00000001</span>
<span class="hljs-number">0x7ffffffee160</span>: <span class="hljs-number">0x00000001</span>      <span class="hljs-number">0x00000000</span>      <span class="hljs-number">0x00000001</span>      <span class="hljs-number">0x00000000</span>
<span class="hljs-number">0x7ffffffee170</span>: <span class="hljs-number">0xfffee1a0</span>      <span class="hljs-number">0x00007fff</span>      <span class="hljs-number">0x08000800</span>      <span class="hljs-number">0x00000000</span>
<span class="hljs-number">0x7ffffffee180</span>: <span class="hljs-number">0xfffee288</span>      <span class="hljs-number">0x00007fff</span>      <span class="hljs-number">0x08000610</span>      <span class="hljs-number">0x00000001</span>
<span class="hljs-number">0x7ffffffee190</span>: <span class="hljs-number">0xfffee280</span>      <span class="hljs-number">0x00007fff</span>      <span class="hljs-number">0x00000000</span>      <span class="hljs-number">0x00000000</span>
<span class="hljs-number">0x7ffffffee1a0</span>: <span class="hljs-number">0x08000830</span>      <span class="hljs-number">0x00000000</span>      <span class="hljs-number">0xff021bf7</span>      <span class="hljs-number">0x00007fff</span>
<span class="hljs-number">0x7ffffffee1b0</span>: <span class="hljs-number">0x00000001</span>      <span class="hljs-number">0x00000000</span>      <span class="hljs-number">0xfffee288</span>      <span class="hljs-number">0x00007fff</span>
(gdb) frame
#<span class="hljs-number">0</span>  sum_till_MAX (n=<span class="hljs-number">2</span>) at /mnt/c/Users/kunzh/C&amp;C++/test/gdb-stack/sum.c:<span class="hljs-number">15</span>
<span class="hljs-number">15</span>          <span class="hljs-keyword">if</span> (n &lt; max_addend)
(gdb) frame <span class="hljs-number">1</span>
#<span class="hljs-number">1</span>  <span class="hljs-number">0x0000000008000745</span> <span class="hljs-keyword">in</span> sum_till_MAX (n=<span class="hljs-number">1</span>)
    at /mnt/c/Users/kunzh/C&amp;C++/test/gdb-stack/sum.c:<span class="hljs-number">16</span>
<span class="hljs-number">16</span>              sum += sum_till_MAX(n);
(gdb) i r rip rbp rsp
rip            <span class="hljs-number">0x8000745</span>        <span class="hljs-number">0x8000745</span> &lt;sum_till_MAX(unsigned <span class="hljs-built_in">int</span>)+<span class="hljs-number">43</span>&gt;
rbp            <span class="hljs-number">0x7ffffffee170</span>   <span class="hljs-number">0x7ffffffee170</span>
rsp            <span class="hljs-number">0x7ffffffee150</span>   <span class="hljs-number">0x7ffffffee150</span>
(gdb) up
#<span class="hljs-number">2</span>  <span class="hljs-number">0x0000000008000800</span> <span class="hljs-keyword">in</span> main (argc=<span class="hljs-number">1</span>, argv=<span class="hljs-number">0x7ffffffee298</span>)
    at /mnt/c/Users/kunzh/C&amp;C++/test/gdb-stack/sum.c:<span class="hljs-number">29</span>
<span class="hljs-number">29</span>          usum = sum_till_MAX(<span class="hljs-number">0</span>);</code></pre>
<pre><code class="hljs apache"><span class="hljs-comment"># 栈帧 0</span>
<span class="hljs-attribute">0x7ffffffee120</span>: <span class="hljs-number">0</span>x<span class="hljs-number">00000000</span>      <span class="hljs-number">0</span>x<span class="hljs-number">00000000</span>      <span class="hljs-number">0</span>x<span class="hljs-number">00000000</span>      <span class="hljs-number">0</span>x<span class="hljs-number">00000002</span>
                                                                <span class="hljs-comment"># 参数 n</span>
<span class="hljs-attribute">0x7ffffffee130</span>: <span class="hljs-number">0</span>x<span class="hljs-number">00000000</span>      <span class="hljs-number">0</span>x<span class="hljs-number">00000000</span>      <span class="hljs-number">0</span>x<span class="hljs-number">00000002</span>      <span class="hljs-number">0</span>x<span class="hljs-number">00000000</span>       
                                                <span class="hljs-comment"># - sum 注意这个是小端法 --   </span>
<span class="hljs-attribute">0x7ffffffee140</span>: <span class="hljs-number">0</span>xfffee<span class="hljs-number">170</span>      <span class="hljs-number">0</span>x<span class="hljs-number">00007</span>fff      <span class="hljs-number">0</span>x<span class="hljs-number">08000745</span>      <span class="hljs-number">0</span>x<span class="hljs-number">00000000</span>
                <span class="hljs-comment"># ------ 上层 $rbp -------      # ---- 返回地址(返回#1) ---</span>
<span class="hljs-comment"># 栈帧 1</span>
<span class="hljs-attribute">0x7ffffffee150</span>: <span class="hljs-number">0</span>xfffee<span class="hljs-number">1</span>b<span class="hljs-number">8</span>      <span class="hljs-number">0</span>x<span class="hljs-number">00007</span>fff      <span class="hljs-number">0</span>x<span class="hljs-number">00</span>f<span class="hljs-number">0</span>b<span class="hljs-number">5</span>ff      <span class="hljs-number">0</span>x<span class="hljs-number">00000001</span>
                                                                <span class="hljs-comment"># 上一层 n</span>
<span class="hljs-attribute">0x7ffffffee160</span>: <span class="hljs-number">0</span>x<span class="hljs-number">00000001</span>      <span class="hljs-number">0</span>x<span class="hljs-number">00000000</span>      <span class="hljs-number">0</span>x<span class="hljs-number">00000001</span>      <span class="hljs-number">0</span>x<span class="hljs-number">00000000</span>
<span class="hljs-attribute">0x7ffffffee170</span>: <span class="hljs-number">0</span>xfffee<span class="hljs-number">1</span>a<span class="hljs-number">0</span>      <span class="hljs-number">0</span>x<span class="hljs-number">00007</span>fff      <span class="hljs-number">0</span>x<span class="hljs-number">08000800</span>      <span class="hljs-number">0</span>x<span class="hljs-number">00000000</span>
                <span class="hljs-comment"># ------ 上层 $rbp -------      # ---- 返回地址(返回#2) ---</span>
<span class="hljs-comment"># 再往上</span>
<span class="hljs-attribute">0x7ffffffee180</span>: <span class="hljs-number">0</span>xfffee<span class="hljs-number">288</span>      <span class="hljs-number">0</span>x<span class="hljs-number">00007</span>fff      <span class="hljs-number">0</span>x<span class="hljs-number">08000610</span>      <span class="hljs-number">0</span>x<span class="hljs-number">00000001</span>
<span class="hljs-attribute">0x7ffffffee190</span>: <span class="hljs-number">0</span>xfffee<span class="hljs-number">280</span>      <span class="hljs-number">0</span>x<span class="hljs-number">00007</span>fff      <span class="hljs-number">0</span>x<span class="hljs-number">00000000</span>      <span class="hljs-number">0</span>x<span class="hljs-number">00000000</span>
<span class="hljs-attribute">0x7ffffffee1a0</span>: <span class="hljs-number">0</span>x<span class="hljs-number">08000830</span>      <span class="hljs-number">0</span>x<span class="hljs-number">00000000</span>      <span class="hljs-number">0</span>xff<span class="hljs-number">021</span>bf<span class="hljs-number">7</span>      <span class="hljs-number">0</span>x<span class="hljs-number">00007</span>fff
<span class="hljs-attribute">0x7ffffffee1b0</span>: <span class="hljs-number">0</span>x<span class="hljs-number">00000001</span>      <span class="hljs-number">0</span>x<span class="hljs-number">00000000</span>      <span class="hljs-number">0</span>xfffee<span class="hljs-number">288</span>      <span class="hljs-number">0</span>x<span class="hljs-number">00007</span>fff</code></pre>
<h3 id="栈大小的限制"><a class="markdownIt-Anchor" href="#栈大小的限制"></a> 栈大小的限制</h3>
<p>尝试不带参数执行 <em>sum</em></p>
<pre><code class="hljs awk">uusl@DESKTOP-A9HV523:<span class="hljs-regexp">/mnt/</span>c<span class="hljs-regexp">/Users/</span>kunzh<span class="hljs-regexp">/C&amp;C++/</span>test<span class="hljs-regexp">/gdb-stack$ ./</span>sum
Segmentation fault (core dumped)</code></pre>
<p>发生了栈溢出 (stack overflow)。下面通过 GDB 来查看具体是怎样错误的。</p>
<ul>
<li><code>run</code> 运行，直到发生了段错误，无法访问某个内存地址(<code>0x7fffff7eeffc</code>)，此时大约在某次<code>sum_till_MAX</code>的开头位置</li>
<li>查看程序计数器，当前执行的指令是一条向内存的写指令，结合程序可知这是停止前想要访问的最低地址</li>
<li>查看栈指针和栈基指针位置，当前为<code>0x7fffff7eeff0</code>和<code>0x7fffff7ef010</code>，<code>-0x14(%rbp)</code>正好为<code>0x7fffff7eeffc</code>。</li>
<li>查看该进程的内存映射(memory map)，显示与被调试的进程相对应的<code>/proc/&lt;PID&gt;/maps</code>的信息。其中，倒数第二行即表示栈空间，栈顶为<code>0x7ffffffef000</code>，显然，刚刚的栈指针已经超出了栈的范围，即栈溢出</li>
</ul>
<pre><code class="hljs crystal">(gdb) r
Starting <span class="hljs-symbol">program:</span> /mnt/c/Users/kunzh/C&amp;C++<span class="hljs-regexp">/test/gdb</span>-stack/sum

Program received signal SIGSEGV, Segmentation fault.
<span class="hljs-number">0x0000000008000722</span> in sum_till_MAX (n=&lt;error reading <span class="hljs-symbol">variable:</span> Cannot access memory at address <span class="hljs-number">0x7fffff7eeffc</span>&gt;)
    at /mnt/c/Users/kunzh/C&amp;C++<span class="hljs-regexp">/test/gdb</span>-stack/sum.<span class="hljs-symbol">c:</span><span class="hljs-number">11</span>
<span class="hljs-number">11</span>      &#123;
(gdb) x/i $pc
=&gt; <span class="hljs-number">0x8000722</span> &lt;sum_till_MAX(unsigned int)+<span class="hljs-number">8</span>&gt;:    mov    %edi,-<span class="hljs-number">0x14</span>(%rbp)
(gdb) p $sp
$<span class="hljs-number">1</span> = (void *) <span class="hljs-number">0x7fffff7eeff0</span>
(gdb) i r rbp
rbp            <span class="hljs-number">0x7fffff7ef010</span>   <span class="hljs-number">0x7fffff7ef010</span>
(gdb) i proc mapping
process <span class="hljs-number">307</span>
Mapped address <span class="hljs-symbol">spaces:</span>

          Start Addr           End Addr       Size     Offset objfile
           <span class="hljs-number">0x8000000</span>          <span class="hljs-number">0x8001000</span>     <span class="hljs-number">0x1000</span>        <span class="hljs-number">0x0</span> /mnt/c/Users/kunzh/C&amp;C++<span class="hljs-regexp">/test/gdb</span>-stack/sum
           <span class="hljs-number">0x8200000</span>          <span class="hljs-number">0x8201000</span>     <span class="hljs-number">0x1000</span>        <span class="hljs-number">0x0</span> /mnt/c/Users/kunzh/C&amp;C++<span class="hljs-regexp">/test/gdb</span>-stack/sum
           <span class="hljs-number">0x8201000</span>          <span class="hljs-number">0x8202000</span>     <span class="hljs-number">0x1000</span>     <span class="hljs-number">0x1000</span> /mnt/c/Users/kunzh/C&amp;C++<span class="hljs-regexp">/test/gdb</span>-stack/sum
      <span class="hljs-number">0x7fffff000000</span>     <span class="hljs-number">0x7fffff1e7000</span>   <span class="hljs-number">0x1e7000</span>        <span class="hljs-number">0x0</span> /<span class="hljs-class"><span class="hljs-keyword">lib</span>/<span class="hljs-title">x86_64</span>-<span class="hljs-title">linux</span>-<span class="hljs-title">gnu</span>/<span class="hljs-title">libc</span>-2.27.<span class="hljs-title">so</span></span>
      <span class="hljs-number">0x7fffff1e7000</span>     <span class="hljs-number">0x7fffff1f0000</span>     <span class="hljs-number">0x9000</span>   <span class="hljs-number">0x1e7000</span> /<span class="hljs-class"><span class="hljs-keyword">lib</span>/<span class="hljs-title">x86_64</span>-<span class="hljs-title">linux</span>-<span class="hljs-title">gnu</span>/<span class="hljs-title">libc</span>-2.27.<span class="hljs-title">so</span></span>
      <span class="hljs-number">0x7fffff1f0000</span>     <span class="hljs-number">0x7fffff3e7000</span>   <span class="hljs-number">0x1f7000</span>   <span class="hljs-number">0x1f0000</span> /<span class="hljs-class"><span class="hljs-keyword">lib</span>/<span class="hljs-title">x86_64</span>-<span class="hljs-title">linux</span>-<span class="hljs-title">gnu</span>/<span class="hljs-title">libc</span>-2.27.<span class="hljs-title">so</span></span>
      <span class="hljs-number">0x7fffff3e7000</span>     <span class="hljs-number">0x7fffff3eb000</span>     <span class="hljs-number">0x4000</span>   <span class="hljs-number">0x1e7000</span> /<span class="hljs-class"><span class="hljs-keyword">lib</span>/<span class="hljs-title">x86_64</span>-<span class="hljs-title">linux</span>-<span class="hljs-title">gnu</span>/<span class="hljs-title">libc</span>-2.27.<span class="hljs-title">so</span></span>
      <span class="hljs-number">0x7fffff3eb000</span>     <span class="hljs-number">0x7fffff3ed000</span>     <span class="hljs-number">0x2000</span>   <span class="hljs-number">0x1eb000</span> /<span class="hljs-class"><span class="hljs-keyword">lib</span>/<span class="hljs-title">x86_64</span>-<span class="hljs-title">linux</span>-<span class="hljs-title">gnu</span>/<span class="hljs-title">libc</span>-2.27.<span class="hljs-title">so</span></span>
      <span class="hljs-number">0x7fffff3ed000</span>     <span class="hljs-number">0x7fffff3f1000</span>     <span class="hljs-number">0x4000</span>        <span class="hljs-number">0x0</span>
      <span class="hljs-number">0x7fffff400000</span>     <span class="hljs-number">0x7fffff403000</span>     <span class="hljs-number">0x3000</span>        <span class="hljs-number">0x0</span> /<span class="hljs-class"><span class="hljs-keyword">lib</span>/<span class="hljs-title">x86_64</span>-<span class="hljs-title">linux</span>-<span class="hljs-title">gnu</span>/<span class="hljs-title">ld</span>-2.27.<span class="hljs-title">so</span></span>
      <span class="hljs-number">0x7fffff403000</span>     <span class="hljs-number">0x7fffff404000</span>     <span class="hljs-number">0x1000</span>     <span class="hljs-number">0x3000</span> /<span class="hljs-class"><span class="hljs-keyword">lib</span>/<span class="hljs-title">x86_64</span>-<span class="hljs-title">linux</span>-<span class="hljs-title">gnu</span>/<span class="hljs-title">ld</span>-2.27.<span class="hljs-title">so</span></span>
      <span class="hljs-number">0x7fffff404000</span>     <span class="hljs-number">0x7fffff405000</span>     <span class="hljs-number">0x1000</span>     <span class="hljs-number">0x4000</span> /<span class="hljs-class"><span class="hljs-keyword">lib</span>/<span class="hljs-title">x86_64</span>-<span class="hljs-title">linux</span>-<span class="hljs-title">gnu</span>/<span class="hljs-title">ld</span>-2.27.<span class="hljs-title">so</span></span>
      <span class="hljs-number">0x7fffff405000</span>     <span class="hljs-number">0x7fffff406000</span>     <span class="hljs-number">0x1000</span>     <span class="hljs-number">0x5000</span> /<span class="hljs-class"><span class="hljs-keyword">lib</span>/<span class="hljs-title">x86_64</span>-<span class="hljs-title">linux</span>-<span class="hljs-title">gnu</span>/<span class="hljs-title">ld</span>-2.27.<span class="hljs-title">so</span></span>
      <span class="hljs-number">0x7fffff406000</span>     <span class="hljs-number">0x7fffff407000</span>     <span class="hljs-number">0x1000</span>     <span class="hljs-number">0x6000</span> /<span class="hljs-class"><span class="hljs-keyword">lib</span>/<span class="hljs-title">x86_64</span>-<span class="hljs-title">linux</span>-<span class="hljs-title">gnu</span>/<span class="hljs-title">ld</span>-2.27.<span class="hljs-title">so</span></span>
      <span class="hljs-number">0x7fffff407000</span>     <span class="hljs-number">0x7fffff415000</span>     <span class="hljs-number">0xe000</span>     <span class="hljs-number">0x7000</span> /<span class="hljs-class"><span class="hljs-keyword">lib</span>/<span class="hljs-title">x86_64</span>-<span class="hljs-title">linux</span>-<span class="hljs-title">gnu</span>/<span class="hljs-title">ld</span>-2.27.<span class="hljs-title">so</span></span>
      <span class="hljs-number">0x7fffff415000</span>     <span class="hljs-number">0x7fffff416000</span>     <span class="hljs-number">0x1000</span>    <span class="hljs-number">0x15000</span> /<span class="hljs-class"><span class="hljs-keyword">lib</span>/<span class="hljs-title">x86_64</span>-<span class="hljs-title">linux</span>-<span class="hljs-title">gnu</span>/<span class="hljs-title">ld</span>-2.27.<span class="hljs-title">so</span></span>
      <span class="hljs-number">0x7fffff416000</span>     <span class="hljs-number">0x7fffff417000</span>     <span class="hljs-number">0x1000</span>    <span class="hljs-number">0x16000</span> /<span class="hljs-class"><span class="hljs-keyword">lib</span>/<span class="hljs-title">x86_64</span>-<span class="hljs-title">linux</span>-<span class="hljs-title">gnu</span>/<span class="hljs-title">ld</span>-2.27.<span class="hljs-title">so</span></span>
      <span class="hljs-number">0x7fffff417000</span>     <span class="hljs-number">0x7fffff428000</span>    <span class="hljs-number">0x11000</span>    <span class="hljs-number">0x17000</span> /<span class="hljs-class"><span class="hljs-keyword">lib</span>/<span class="hljs-title">x86_64</span>-<span class="hljs-title">linux</span>-<span class="hljs-title">gnu</span>/<span class="hljs-title">ld</span>-2.27.<span class="hljs-title">so</span></span>
      <span class="hljs-number">0x7fffff428000</span>     <span class="hljs-number">0x7fffff429000</span>     <span class="hljs-number">0x1000</span>    <span class="hljs-number">0x28000</span> /<span class="hljs-class"><span class="hljs-keyword">lib</span>/<span class="hljs-title">x86_64</span>-<span class="hljs-title">linux</span>-<span class="hljs-title">gnu</span>/<span class="hljs-title">ld</span>-2.27.<span class="hljs-title">so</span></span>
      <span class="hljs-number">0x7fffff629000</span>     <span class="hljs-number">0x7fffff62a000</span>     <span class="hljs-number">0x1000</span>    <span class="hljs-number">0x29000</span> /<span class="hljs-class"><span class="hljs-keyword">lib</span>/<span class="hljs-title">x86_64</span>-<span class="hljs-title">linux</span>-<span class="hljs-title">gnu</span>/<span class="hljs-title">ld</span>-2.27.<span class="hljs-title">so</span></span>
      <span class="hljs-number">0x7fffff62a000</span>     <span class="hljs-number">0x7fffff62b000</span>     <span class="hljs-number">0x1000</span>    <span class="hljs-number">0x2a000</span> /<span class="hljs-class"><span class="hljs-keyword">lib</span>/<span class="hljs-title">x86_64</span>-<span class="hljs-title">linux</span>-<span class="hljs-title">gnu</span>/<span class="hljs-title">ld</span>-2.27.<span class="hljs-title">so</span></span>
      <span class="hljs-number">0x7fffff62b000</span>     <span class="hljs-number">0x7fffff62c000</span>     <span class="hljs-number">0x1000</span>        <span class="hljs-number">0x0</span>
      <span class="hljs-number">0x7fffff7e0000</span>     <span class="hljs-number">0x7fffff7e2000</span>     <span class="hljs-number">0x2000</span>        <span class="hljs-number">0x0</span>
      <span class="hljs-number">0x7fffff7ef000</span>     <span class="hljs-number">0x7ffffffef000</span>   <span class="hljs-number">0x800000</span>        <span class="hljs-number">0x0</span> [stack]
      <span class="hljs-number">0x7ffffffef000</span>     <span class="hljs-number">0x7fffffff0000</span>     <span class="hljs-number">0x1000</span>        <span class="hljs-number">0x0</span> [vdso]</code></pre>
<p>查看上述运行环境的栈空间，大小为</p>
<pre><code class="hljs awk">uusl@DESKTOP-A9HV523:<span class="hljs-regexp">/mnt/</span>c<span class="hljs-regexp">/Users/</span>kunzh$ ulimit -s
<span class="hljs-number">8192</span></code></pre>
<p>由于<code>wsl</code>不能直接调整，换台机子演示一下</p>
<pre><code class="hljs angelscript"># uusl @ iZuf62y6fwj9mvjt3q1hjjZ <span class="hljs-keyword">in</span> ~/document/test [<span class="hljs-number">15</span>:<span class="hljs-number">21</span>:<span class="hljs-number">44</span>] C:<span class="hljs-number">139</span>
$ ulimit -s
<span class="hljs-number">8192</span>

# uusl @ iZuf62y6fwj9mvjt3q1hjjZ <span class="hljs-keyword">in</span> ~/document/test [<span class="hljs-number">15</span>:<span class="hljs-number">21</span>:<span class="hljs-number">51</span>]
$ ulimit -Ss <span class="hljs-number">81920</span>

# uusl @ iZuf62y6fwj9mvjt3q1hjjZ <span class="hljs-keyword">in</span> ~/document/test [<span class="hljs-number">15</span>:<span class="hljs-number">21</span>:<span class="hljs-number">57</span>]
$ ./sum
sum(<span class="hljs-number">0.</span><span class="hljs-number">.1048576</span>) = <span class="hljs-number">549756338176</span></code></pre>
<p>上面调整栈空间为原来的10倍，便能正常运行程序了，计算的是 0 到 1048576 的整数之和。</p>
<h3 id="扩展"><a class="markdownIt-Anchor" href="#扩展"></a> 扩展</h3>
<p>以 backtrace 检查栈固然是调试的常用做法，但有时栈破坏会导致问题难以分析。如这样：</p>
<pre><code class="hljs angelscript">(gdb) bt
#<span class="hljs-number">0</span>  <span class="hljs-number">0x0000003b4869ac80</span> <span class="hljs-keyword">in</span> nanosleep() <span class="hljs-keyword">from</span> /lib64/libc.so<span class="hljs-number">.6</span>
#<span class="hljs-number">1</span>  <span class="hljs-number">0x000ee1c2000ee1c1</span> <span class="hljs-keyword">in</span> ?? ()
#<span class="hljs-number">2</span>  <span class="hljs-number">0x000ee1c2000ee1c3</span> <span class="hljs-keyword">in</span> ?? ()
#<span class="hljs-number">3</span>  <span class="hljs-number">0x000ee1c2000ee1c5</span> <span class="hljs-keyword">in</span> ?? ()
#<span class="hljs-number">4</span>  <span class="hljs-number">0x000ee1c2000ee1c7</span> <span class="hljs-keyword">in</span> ?? ()
......
#<span class="hljs-number">11</span> <span class="hljs-number">0x0000000000400d02</span> <span class="hljs-keyword">in</span> th_rep (p=<span class="hljs-number">0x1877c90</span>) at bug.c:<span class="hljs-number">167</span></code></pre>
<p>(gdb) backtrace 是根据栈里保存的函数返回地址来显示的，根据栈空间上的返回地址和调试信息得出栈使用量，依次求出调用者函数。因此，如果程序涉及栈被破坏，backtrace 便不再可靠。例如，在多线程环境中，A 线程将其栈指针 SP 传给 B 线程，请求处理栈上的一段数据，但 B 线程因阻塞等原因未能及时反应，此时 A 线程此操作等待超时，继续执行其他指令，调用函数的过程中在 SP 原位置存放了某个返回地址，此后 B 线程把接受到的指针指向的这段数据处理掉，破坏了该返回地址，A 的栈被破坏。</p>
<p>因此在使用 bt 时还需联系其他信息，综合考虑。</p>

            </div>
            <hr>
            <div>
              <div class="post-metas mb-3">
                
                  <div class="post-meta mr-3">
                    <i class="iconfont icon-category"></i>
                    
                      <a class="hover-with-bg" href="/categories/%E7%BC%96%E7%A8%8B/">编程</a>
                    
                  </div>
                
                
                  <div class="post-meta">
                    <i class="iconfont icon-tags"></i>
                    
                      <a class="hover-with-bg" href="/tags/c/">c</a>
                    
                      <a class="hover-with-bg" href="/tags/c/">c++</a>
                    
                      <a class="hover-with-bg" href="/tags/linux/">linux</a>
                    
                      <a class="hover-with-bg" href="/tags/vscode/">vscode</a>
                    
                      <a class="hover-with-bg" href="/tags/gdb/">gdb</a>
                    
                  </div>
                
              </div>
              
              
                <div class="post-prevnext row">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/2020/11/bomblab/">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">bomb lab</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/2020/09/%E7%BA%BF%E6%80%A7%E6%97%B6%E9%97%B4%E6%8E%92%E5%BA%8F/">
                        <span class="hidden-mobile">线性时间排序</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
              <!-- Comments -->
              <article class="comments" id="comments">
                
                
  <div id="vcomments"></div>
  <script type="text/javascript">
    function loadValine() {
      addScript('https://cdn.staticfile.org/valine/1.4.14/Valine.min.js', function () {
        new Valine({
          el: "#vcomments",
          app_id: "iAgkjaR2s2ws1XXtS5sVxE7H-MdYXbMMI",
          app_key: "vKka6XRlblVTkbKz8jLXx6EQ",
          placeholder: "你是来自评论区的小惊喜吗 ...",
          path: window.location.pathname,
          avatar: "retro",
          meta: ["nick","mail"],
          pageSize: "10",
          lang: "zh-CN",
          highlight: false,
          recordIP: true,
          serverURLs: "",
        });
      });
    }
    waitElementVisible('vcomments', loadValine);
  </script>
  <noscript>Please enable JavaScript to view the <a target="_blank" href="https://valine.js.org" rel="nofollow noopener noopener">comments
      powered by Valine.</a></noscript>


<!-- 
  <div id="vcomments"></div>
  <script type="text/javascript">
    function loadValine() {
      addScript('https://cdn.staticfile.org/valine/1.4.14/Valine.min.js', function () {
        new Valine({
          el: "#vcomments",
          enableQQ: true,
          boolean: true,
          app_id: "iAgkjaR2s2ws1XXtS5sVxE7H-MdYXbMMI",
          app_key: "vKka6XRlblVTkbKz8jLXx6EQ",
          placeholder: "你是来自评论区的小惊喜吗 ...",
          path: "window.location.pathname",
          avatar: "retro",
          meta: "["nick","mail"]",
          pageSize: "10",
          lang: "zh-CN",
          highlight: false,
          recordIP: true,
          serverURLs: "",
            // 设置Bilibili表情包地址
            emojiCDN: '//i0.hdslb.com/bfs/emote/', 
            // 表情title和图片映射
            emojiMaps: {
            "tv_doge": "6ea59c827c414b4a2955fe79e0f6fd3dcd515e24.png",
            "tv_亲亲": "a8111ad55953ef5e3be3327ef94eb4a39d535d06.png",
            "tv_偷笑": "bb690d4107620f1c15cff29509db529a73aee261.png",
            "tv_再见": "180129b8ea851044ce71caf55cc8ce44bd4a4fc8.png",
            "tv_冷漠": "b9cbc755c2b3ee43be07ca13de84e5b699a3f101.png",
            "tv_发怒": "34ba3cd204d5b05fec70ce08fa9fa0dd612409ff.png",
            "tv_发财": "34db290afd2963723c6eb3c4560667db7253a21a.png",
            "tv_可爱": "9e55fd9b500ac4b96613539f1ce2f9499e314ed9.png",
            "tv_吐血": "09dd16a7aa59b77baa1155d47484409624470c77.png",
            "tv_呆": "fe1179ebaa191569b0d31cecafe7a2cd1c951c9d.png",
            "tv_呕吐": "9f996894a39e282ccf5e66856af49483f81870f3.png",
            "tv_困": "241ee304e44c0af029adceb294399391e4737ef2.png",
            "tv_坏笑": "1f0b87f731a671079842116e0991c91c2c88645a.png",
            "tv_大佬": "093c1e2c490161aca397afc45573c877cdead616.png",
            "tv_大哭": "23269aeb35f99daee28dda129676f6e9ea87934f.png",
            "tv_委屈": "d04dba7b5465779e9755d2ab6f0a897b9b33bb77.png",
            "tv_害羞": "a37683fb5642fa3ddfc7f4e5525fd13e42a2bdb1.png",
            "tv_尴尬": "7cfa62dafc59798a3d3fb262d421eeeff166cfa4.png",
            "tv_微笑": "70dc5c7b56f93eb61bddba11e28fb1d18fddcd4c.png",
            "tv_思考": "90cf159733e558137ed20aa04d09964436f618a1.png",
            "tv_惊吓": "0d15c7e2ee58e935adc6a7193ee042388adc22af.png",
            "tv_打脸": "56ab10b624063e966bfcb76ea5dc4794d87dfd47.png",
            "tv_抓狂": "fe31c08edad661d63762b04e17b8d5ae3c71a757.png",
            "tv_抠鼻": "c666f55e88d471e51bbd9fab9bb308110824a6eb.png",
            "tv_斜眼笑": "911f987aa8bc1bee12d52aafe62bc41ef4474e6c.png",
            "tv_无奈": "ea8ed89ee9878f2fece2dda0ea8a5dbfe21b5751.png",
            "tv_晕": "5443c22b4d07fb1907ccc610c8e6db254f2461b7.png",
            "tv_流汗": "cead1c351ab8d79e9f369605beb90148db0fbed3.png",
            "tv_流泪": "7e71cde7858f0cd50d74b0264aa26db612a8a167.png",
            "tv_流鼻血": "c32d39db2737f89b904ca32700d140a9241b0767.png",
            "tv_点赞": "f85c354995bd99e28fc76c869bfe42ba6438eff4.png",
            "tv_生气": "26702dcafdab5e8225b43ffd23c94ac1ff932654.png",
            "tv_生病": "8b0ec90e6b86771092a498c54f09fc94621c1900.png",
            "tv_疑问": "0793d949b18d7be716078349c202c15ff166f314.png",
            "tv_白眼": "c1d59f439e379ee50eef488bcb5e5378e5044ea4.png",
            "tv_皱眉": "72ccad6679fea0d14cce648b4d818e09b8ffea2d.png",
            "tv_目瞪口呆": "0b8cb81a68de5d5365212c99375e7ace3e7891b7.png",
            "tv_睡着": "8b196675b53af58264f383c50ad0945048290b33.png",
            "tv_笑哭": "1abc628f6d4f4caf9d0e7800878f4697abbc8273.png",
            "tv_腼腆": "89712c0d4af73e67f89e35cbc518420380a7f6f4.png",
            "tv_色": "61822c7e9aae5da76475e7892534545336b23a6f.png",
            "tv_调侃": "4bc022533ef31544ca0d72c12c808cf4a1cce3e3.png",
            "tv_调皮": "b9c41de8e82dd7a8515ae5e3cb63e898bf245186.png",
            "tv_鄙视": "6e72339f346a692a495b123174b49e4e8e781303.png",
            "tv_闭嘴": "c9e990da7f6e93975e25fd8b70e2e290aa4086ef.png",
            "tv_难过": "87f46748d3f142ebc6586ff58860d0e2fc8263ba.png",
            "tv_馋": "fc7e829b845c43c623c8b490ee3602b7f0e76a31.png",
            "tv_鬼脸": "0ffbbddf8a94d124ca2f54b360bbc04feb6bbfea.png",
            "tv_黑人问号": "45821a01f51bc867da9edbaa2e070410819a95b2.png",
            "tv_鼓掌": "1d21793f96ef4e6f48b23e53e3b9e42da833a0f6.png"
                // ... 更多表情
            }
        });
      });
    }
    createObserver(loadValine, 'vcomments');
  </script>
      <style>
        #vcomments textarea {
            box-sizing: border-box;
            background: url("/img/v2-f3d5c26e7ac0da80ee72b6dc178d6aa1_b005.gif") 100% 100% no-repeat;
        }
      </style>
  <noscript>Please enable JavaScript to view the <a target="_blank" href="https://valine.js.org" rel="nofollow noopener noopener">comments
      powered by Valine.</a></noscript>
 -->

              </article>
            
          </article>
        </div>
      </div>
    </div>
    
      <div class="d-none d-lg-block col-lg-2 toc-container" id="toc-ctn">
        <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;目录</p>
  <div id="tocbot"></div>
</div>

      </div>
    
  </div>
</div>

<!-- Custom -->

  <div class="col-lg-7 mx-auto nopadding-md">
    <div class="container custom post-content mx-auto">
      <img src="/img/371905140-ROBOT-WAVING-400px-unscreen(1).gif" srcset="/img/loading.gif" class="rounded mx-auto d-block mt-5" style="width:200px; height:200px;" >
    </div>
  </div>


    
  </main>

  
    <a id="scroll-top-button" href="#" role="button">
      <i class="iconfont icon-arrowup" aria-hidden="true"></i>
    </a>
  

  
    <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v"
                 for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>
  

  

  

  <footer class="mt-5">
  <div class="text-center py-3">
    <div>
      <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a>
      <i class="iconfont icon-love"></i>
      <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener">
        <span>Fluid</span></a>
        <br>
        <span>©2019 - 2020 By</span>
        <a href="https://github.com/rainrime" target="_blank" rel="nofollow noopener"><span>kunzh</span></a>
    </div>
    
  <div class="statistics">
    
    

    
      
        <!-- 不蒜子统计PV -->
        <span id="busuanzi_container_site_pv" style="display: none">
            总访问量 
            <span id="busuanzi_value_site_pv"></span>
             次
          </span>
      
      
        <!-- 不蒜子统计UV -->
        <span id="busuanzi_container_site_uv" style="display: none">
            总访客数 
            <span id="busuanzi_value_site_uv"></span>
             人
          </span>
      
    
  </div>


    

    
  </div>
</footer>


<!-- SCRIPTS -->
<script  src="https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js" ></script>
<script  src="https://cdn.staticfile.org/twitter-bootstrap/4.4.1/js/bootstrap.min.js" ></script>
<script  src="/js/debouncer.js" ></script>
<script  src="/js/main.js" ></script>

<!-- Plugins -->


  
    <script  src="/js/lazyload.js" ></script>
  



  



  <script defer src="https://cdn.staticfile.org/clipboard.js/2.0.6/clipboard.min.js" ></script>
  <script  src="/js/clipboard-use.js" ></script>



  <script defer src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" ></script>





  <script  src="https://cdn.staticfile.org/tocbot/4.11.1/tocbot.min.js" ></script>
  <script>
    $(document).ready(function () {
      var boardCtn = $('#board-ctn');
      var boardTop = boardCtn.offset().top;

      tocbot.init({
        tocSelector: '#tocbot',
        contentSelector: '#post-body',
        headingSelector: 'h1,h2,h3,h4,h5,h6',
        linkClass: 'tocbot-link',
        activeLinkClass: 'tocbot-active-link',
        listClass: 'tocbot-list',
        isCollapsedClass: 'tocbot-is-collapsed',
        collapsibleClass: 'tocbot-is-collapsible',
        collapseDepth: 6,
        scrollSmooth: true,
        headingsOffset: -boardTop
      });
      if ($('.toc-list-item').length > 0) {
        $('#toc').css('visibility', 'visible');
      }
    });
  </script>



  <script  src="https://cdn.staticfile.org/typed.js/2.0.11/typed.min.js" ></script>
  <script>
    var typed = new Typed('#subtitle', {
      strings: [
        '  ',
        "gdb 调试——栈&nbsp;",
      ],
      cursorChar: "_",
      typeSpeed: 70,
      loop: false,
    });
    typed.stop();
    $(document).ready(function () {
      $(".typed-cursor").addClass("h2");
      typed.start();
    });
  </script>



  <script  src="https://cdn.staticfile.org/anchor-js/4.2.2/anchor.min.js" ></script>
  <script>
    anchors.options = {
      placement: "right",
      visible: "hover",
      
      icon: "❡"
      
    };
    var el = "h1,h2,h3,h4,h5,h6".split(",");
    var res = [];
    for (item of el) {
      res.push(".markdown-body > " + item)
    }
    anchors.add(res.join(", "))
  </script>



  <script  src="/js/local-search.js" ></script>
  <script>
    var path = "/local-search.xml";
    var inputArea = document.querySelector("#local-search-input");
    inputArea.onclick = function () {
      searchFunc(path, 'local-search-input', 'local-search-result');
      this.onclick = null
    }
  </script>



  <script  src="https://cdn.staticfile.org/fancybox/3.5.7/jquery.fancybox.min.js" ></script>
  <link  rel="stylesheet" href="https://cdn.staticfile.org/fancybox/3.5.7/jquery.fancybox.min.css" />

  <script>
    $('#post img:not(.no-zoom img, img[no-zoom]), img[zoom]').each(
      function () {
        var element = document.createElement('a');
        $(element).attr('data-fancybox', 'images');
        $(element).attr('href', $(this).attr('src'));
        $(this).wrap(element);
      }
    );
  </script>







  
  
    <script type="text/javascript">
      //定义获取词语下标
      var a_idx = 0;
      jQuery(document).ready(function ($) {
        //点击body时触发事件
        $("body").click(function (e) {
          //需要显示的词语
          var a = new Array("富强", "民主", "文明", "和谐", "自由", "平等", "公正", "法治", "爱国", "敬业", "诚信", "友善");
          //设置词语给span标签
          var $i = $("<span/>").text(a[a_idx]);
          //下标等于原来下标+1  余 词语总数
          a_idx = (a_idx + 1) % a.length;
          //获取鼠标指针的位置，分别相对于文档的左和右边缘。
          //获取x和y的指针坐标
          var x = e.pageX, y = e.pageY;
          //在鼠标的指针的位置给$i定义的span标签添加css样式
          $i.css({
            "z-index": 999,
            "top": y - 20,
            "left": x,
            "position": "absolute",
            "font-weight": "bold",
            "color": rand_color()
          });
          // 随机颜色
          function rand_color() {
            return "rgb(" + ~~(255 * Math.random()) + "," + ~~(255 * Math.random()) + "," + ~~(255 * Math.random()) + ")"
          }
          //在body添加这个标签
          $("body").append($i);
          //animate() 方法执行 CSS 属性集的自定义动画。
          //该方法通过CSS样式将元素从一个状态改变为另一个状态。CSS属性值是逐渐改变的，这样就可以创建动画效果。
          //详情请看http://www.w3school.com.cn/jquery/effect_animate.asp
          $i.animate({
            //将原来的位置向上移动180
            "top": y - 180,
            "opacity": 0
            //1500动画的速度
          }, 1500, function () {
            //时间到了自动删除
            $i.remove();
          });
        });
      })
      ;
    </script>
  



  <script>(function (i, s, o, g, r, a, m) {
      i['DaoVoiceObject'] = r;
      i[r] = i[r] ||
        function () {
          (i[r].q = i[r].q || []).push(arguments);
        };
      i[r].l = 1 * new Date();
      a = s.createElement(o);
      m = s.getElementsByTagName(o)[0];
      a.async = 1;
      a.src = g;
      a.charset = 'utf-8';
      m.parentNode.insertBefore(a, m);
    })(window, document, 'script', ('https:' === document.location.protocol ? 'https:' : 'http:') + "//widget.daovoice.io/widget/244aa65c.js", 'daovoice');
    daovoice('init', {
      app_id: "244aa65c",
    });
    daovoice('update');
  </script>









  

  

  

  

  

  





</body>
</html>
